#include "D3DApp.h"
#include "MainState.h"
#include "GeneratingState.h"
#include "Game.h"


#include <iostream>
#include <string>


#include <assert.h>

#define MAX_LENGTH 2000

#define _CRTDBG_MAP_ALLOC
#include <stdlib.h>
#include <crtdbg.h>
#include <string>

#undef main
#define MAX_LENGTH 2000

LRESULT CALLBACK WindowProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam);

int WINAPI WinMain(HINSTANCE hInstance,
	HINSTANCE hPrevInstance,
	LPSTR lpCmdLine,
	int nCmdShow)
{

	HWND hWnd;
	WNDCLASSEX wc;

	ZeroMemory(&wc, sizeof(WNDCLASSEX));

	wc.cbSize = sizeof(WNDCLASSEX);
	wc.style = CS_HREDRAW | CS_VREDRAW;
	wc.lpfnWndProc = WindowProc;
	wc.hInstance = hInstance;
	wc.hCursor = LoadCursor(NULL, IDC_ARROW);
	wc.hbrBackground = (HBRUSH)COLOR_WINDOW;
	wc.lpszClassName = L"WindowClass";

	RegisterClassEx(&wc);

	hWnd = CreateWindowEx(NULL,
		L"WindowClass",
		L"Dx FrameWork ver 1.0",
		WS_OVERLAPPEDWINDOW,
		560, 300,
		800, 600,
		NULL,
		NULL,
		hInstance,
		NULL);

	ShowWindow(hWnd, nCmdShow);

	_CrtDumpMemoryLeaks();


	TheD3DApp::Instance()->Init(hWnd);

	TheGame::Instance()->Init();
	TheGame::Instance()->ChangeState(MainState::Instance());
	//TheGame::Instance()->ChangeState(GeneratingState::Instance());

	// main loop:

	MSG msg;

	__int64 countsPerSec = 0;
	QueryPerformanceFrequency((LARGE_INTEGER*)&countsPerSec);

	float secsPerCount = 1.0f / (float)countsPerSec;

	__int64 prevTimestamp = 0;
	QueryPerformanceCounter((LARGE_INTEGER*)&prevTimestamp);

	while(TRUE)
	{


		while(PeekMessage(&msg, NULL, 0, 0, PM_REMOVE))
		{
			TranslateMessage(&msg);
			DispatchMessage(&msg);
		}

		if(msg.message == WM_QUIT)
			break;

		__int64 currentTimestamp =  0;
		QueryPerformanceCounter((LARGE_INTEGER*)&currentTimestamp);
		float dt = (currentTimestamp  - prevTimestamp)* secsPerCount;


		TheGame::Instance()->Render();
		TheGame::Instance()->Update(dt);
		TheGame::Instance()->HandleInput();
		TheGame::Instance()->HandleCollisions();


		prevTimestamp = currentTimestamp;
	}

	TheD3DApp::Instance()->Clean();
	TheGame::Instance()->Clean();

	return msg.wParam;
}

// Message handler
LRESULT CALLBACK WindowProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
	switch(message)
	{
	case WM_DESTROY:
		{
			PostQuitMessage(0);
			return 0;
		} break;
	}

	return DefWindowProc (hWnd, message, wParam, lParam);
}